#####################################################################
# File:         UserSignUp.py
# Product:      KnowledgeEngine
#
# Copyright:    Copyright (c) 2002, Faulkner Ltd.
# Author:       Tom Cameron
#
# Description:  This file defines the UserSignUp class, a simple
#               container to generate web forms for new users to
#               join the environment
#
# See Also:     ElementContainer, Element
#####################################################################

#####################################################################
## Knowledge Engine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.KnowledgeEngineCore import *
from Products.KnowledgeEngine.ElementContainer import *
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *
from Products.KnowledgeEngine.EventDefinition import *

#####################################################################
## Zope Library Imports
from Globals import DTMLFile
from ImageFile import ImageFile

#####################################################################
## Python Library Imports
# (none)

#####################################################################
## UserAccessRulesInfo Class Definition
class UserSignUpInfo(ElementContainerInfo):
    """
        Defines the class info methods, defining information about
        the class without needing an instance of the class
    """

    #---------------------------------------------------------------#

    def getClassName(self):
        """
            Returns the name of the class for which
            we are providing information.
        """
        return "UserSignUp"

    #---------------------------------------------------------------#

    def getDisplayName(self):
        """
            Return a friendly name for the class instances
            (this is used for displaying in lists etc)
        """

        return "User SignUp"

    #---------------------------------------------------------------#

    def getIdentityType(self):
        """
            Return the identity type.
        """

        return "usu"

    #---------------------------------------------------------------#

    def getClassIcon(self):
        """
            Return the appropriate icon file for the class.
        """

        return ImageFile('www/icon.gif', globals())

    #---------------------------------------------------------------#

    def isPermittedInContainer(self, containerClassInfo, containerInstance = None, instance=None):
        """
            ABSTRACT: Returns if class instances (instance) is permitted in
            the specified container (containerInstance)

            NOTE: This is from this class' instance perspective.
        """

        #UserSignUp are only permitted in UserAccessManagers
        return containerClassInfo.isInstanceOf('Environment')

    #---------------------------------------------------------------#

    def isChildPermitted(self, childClassInfo, childInstance = None):
        """
            Returns if the specified child is permitted as a
            child of the class' instances.

            NOTE: This is from this class' instance perspective.

            For component containers, this always overrides what the
            return value from childClassInfo.isPermittedInContainer(...)
        """

        #DEFAULT RULE: Models may only contain Sections and Reports
        return childClassInfo.isInstanceOf('Event')

    #---------------------------------------------------------------#

    def onConfigureProperties(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register
            class specific properties using the PropertyReflection interface.

            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered

            NOTE: This method is called before ClassInfo.onAfterStartup()
        """

        #initialise the super-class properties for reflection
        ElementContainerInfo.onConfigureProperties(self)

        #add the standard 'formText' property
        self.addPropertyDefinition(PropertyDefinition(identity="formText", displayName="Form Content Text", description="The text that will display in the signup form", defaultValue="Choose Which Models you would like to have access to", propertyType=pt_STRING, propertyFormat=pf_TEXT_MULTILINE, propertyStructure=ps_ATOMIC))

        #add the standard 'formText' property
        self.addPropertyDefinition(PropertyDefinition(identity="responseText", displayName="Response Content Text", description="The text that will display after a successful signup", defaultValue="Thankyou for joining xxxx. Please proceed to your home area", propertyType=pt_STRING, propertyFormat=pf_TEXT_MULTILINE, propertyStructure=ps_ATOMIC))

        #add the standard 'allowModelSelection' property
        self.addPropertyDefinition(PropertyDefinition(identity="allowModelSelection", displayName="Allow Model Selection", description="Will the new User be allowed to choose their Models", defaultValue=false, propertyType=pt_BOOLEAN, propertyFormat=pf_CHECKBOX, propertyStructure=ps_ATOMIC))

        #add the standard 'modelList' property
        #(the property represents a list of modelids that have been selected by the end-user)
        self.addPropertyDefinition(PropertyDefinition(identity="modelList", displayName="Available Models", description="List which models to allow the user to choose (one per line)", defaultValue=[], propertyType=pt_STRING, propertyFormat=pf_NATIVE, propertyStructure=ps_LIST, hasEnumeratedValues=true, enumeratedValuesFunction=(lambda context:[(model.getTitleOrId(),model.getIdentity()) for model in context.getModels()])))

       #add the standard 'allowModelSelection' property
        self.addPropertyDefinition(PropertyDefinition(identity="maxNumAssessments", displayName="Max Assessments per Model", description="Specify the maximum numer of Assessments per Model", defaultValue=5, propertyType=pt_INTEGER, propertyFormat=pf_NATIVE, propertyStructure=ps_ATOMIC))

    #---------------------------------------------------------------#

    def onConfigureEvents(self):
        """
            Automatically called by the Knowledge Engine once
            the class has been loaded.  Use this method to register
            class specific events using the EventReflection interface.

            If this class is sub-classed, a call must be made to
            the super-class to ensure super-class properties are
            correctly registered

            NOTE: This method is called before ClassInfo.onAfterStartup()
        """

        #initialise the super-class events for reflection
        ElementContainerInfo.onConfigureEvents(self)

        #add the onBeforeSaveAssessment event (which occurs prior to an assessment being saved)
        self.addEventDefinition(EventDefinition(identity="onAfterSignup", displayName="After Signup", description="Occurs after a signup", eventType=et_SERVER))

    #---------------------------------------------------------------#


#####################################################################
## UserSignUp Class Definition
class UserSignUp(ElementContainer):
    """
        A class to represent the UserAccessRules for a User
    """

    #---------------------------------------------------------------#

    #ABSTRACT TRANSIENT: a ClassInfo implementation instance to provide info about this class
    _CLASSINFO = UserSignUpInfo()

    #---------------------------------------------------------------#

    index_html = DTMLFile('dtml/index_html', globals())

    #---------------------------------------------------------------#

    def __init__(self, id, identity):
        "Constructor for the object"

        ElementContainer.__init__(self, id, identity)

        #perform onAfterInstanciation processing
        self.onAfterInstanciation()

    #---------------------------------------------------------------#

    def onAfterInstanciation(self):
        """
            Handle Knowledge Engine specific actions after this object
            has been loaded into memory.

            This is useful for performing backwards compatibility
        """

        #perform default onAfterInstanciation processing
        ElementContainer.onAfterInstanciation(self)

        #add/update the Preview
        self.addManagementTab('Preview', 'index_html', None, false)


    #---------------------------------------------------------------#

    def addUser(self, REQUEST):
        """ creates a new user from the autosignup REQUEST
        """

        errorMessage=""
        ufType=self.getEnvironment().getUserFolderType()
        userFolder=self.getEnvironment().getUserFolders()[0]
        userAccessManager=self.getEnvironment().getUserAccessManager()

        password=REQUEST['password']
        password_confirm=REQUEST['password_confirm']
        username=REQUEST['username']

        if password=='' or password!=password_confirm:
            errorMessage+="Passwords do not match. "
        if len(username)<3:
            errorMessage+="Your chosen Username too short. "
        if username in self.getUserNames():
            errorMessage+="Your chosen Username is already taken. "

        if errorMessage=="":
            #All ok so add user
            if ufType=='exUserFolder':
                userFolder.manage_addUser(REQUEST)
            else:
                REQUEST.set('name',username)
                REQUEST.set('password',password)
                REQUEST.set('confirm',password_confirm)
                #REQUEST.set('domains','')
                #REQUEST.set('roles',roles)
                userFolder.manage_users(submit='Add',REQUEST=REQUEST)

            #create User Access Object
            REQUEST.set('keid',username)
            REQUEST.set('keusername',username)
            uar=userAccessManager.manage_ObjectConstruction(PROPERTIES=REQUEST, COMMAND='CREATE_INSTANCE', CLASSNAME='UserAccessRules')
            #set the access rules
            #build request if the user has not chosen
            if not self.isModelSelectionAllowed():
                a=self.getMaxNumAssessments()
                m=self.getModelIdentityList()
                REQUEST.set('links',m)
                form = {}
                for id in m:
                    form[id] = [a]               #add to form
                REQUEST.set('form',form)        #simulate form
            uar.setModelAccess(REQUEST)

            home=self.getEnvironment().absolute_url() + "/home"
            ret=self.getResponseText() + "<BR><BR>You can now <A href='" + home + "'>login using your new Username and Password</A>"
            return ret

        else:
            ret="Sorry, " + errorMessage + "<BR><BR> <A href='javascript:history.back(1)'>Try again</A>"
            return ret


    #---------------------------------------------------------------#

    def getModelIdentityList(self):
        """
            Returns the List of allowed Models
        """

        return self.modelList

    #---------------------------------------------------------------#

    def getUserNames(self):
        """
            Returns the List of allowed Models
        """

        return [u.getUserName() for u in self.getEnvironment().getAllUsers()]

    #---------------------------------------------------------------#

    def getModelList(self):
        """
            Returns the list of allowed models
        """

        #ret=[]
        #tmp={}
        modelIds=self.getModelIdentityList()
        models=self.getEnvironment().getModels()
        models=[m for m in models if m.getIdentity() in modelIds]
        #for m in models:
        #    if m.getIdentity() in modelIds:
        #        tmp['id']=m.getIdentity()
        #        tmp['title']=m.getTitleOrId()
        #        ret.append(tmp)

        return models

    #---------------------------------------------------------------#

    def getFormText(self):
        """
            Returns the Form Content for the signup form
        """

        return self.formText

    #---------------------------------------------------------------#

    def getResponseText(self):
        """
            Returns the Response Content for the signup form
        """

        return self.responseText

    #---------------------------------------------------------------#

    def getMaxNumAssessments(self):
        """
            Returns the maxNumAssessments
        """

        return self.maxNumAssessments

    #---------------------------------------------------------------#

    def isModelSelectionAllowed(self):
        """
            True if Model selection is allowed
        """

        #perform default onAfterInstanciation processing
        return self.allowModelSelection == true

    #---------------------------------------------------------------#



#####################################################################
## Class Initialisation

# Register Class Information with the Knowledge Engine
registerGenericObjectClass(UserSignUp)

#####################################################################